package com.zqh.ordercheckexpired.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zqh.myfmmall.clients.*;
import com.zqh.myfmmall.constants.OrderCloseType;
import com.zqh.myfmmall.constants.OrderStatus;
import com.zqh.myfmmall.result.Result;
import com.zqh.myfmmall.result.ResultType;
import com.zqh.myfmmall.rowbeans.entity.OrderItem;
import com.zqh.myfmmall.rowbeans.entity.Orders;
import com.zqh.myfmmall.rowbeans.entity.ProductSku;
import com.zqh.ordercheckexpired.service.CheckExpiredOrderService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Description :
 * @Author :kono淇杭哒、
 * @Create 2022-03-01 22:57
 */
@Slf4j
@Service("checkExpiredOrderService")
public class CheckExpiredOrderServiceImpl implements CheckExpiredOrderService{
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private OrderQueryClient orderQueryClient;
    @Autowired
    private OrderUDClient orderUDClient;
    @Autowired
    private OrderItemQueryClient orderItemQueryClient;
    @Autowired
    private OrderItemSaveClient orderItemSaveClient;
    @Autowired
    private ProductSkuCUDClient productSkuCUDClient;
    @Autowired
    private ProductSkuQueryClient productSkuQueryClient;


    /**
     * 功能描述:
     * 查看该id订单是否过期未支付并进行处理
     * @param orderId
     * @return
     * @author kono曾淇杭哒！
     * @date 2022/3/1 22:58
     */
    @Override
    public Result checkExpiredOrder(String orderId) {
        HashMap<String, RLock> redissonLockMap = new HashMap<>();
        ObjectMapper objectMapper = new ObjectMapper();
        Result orderQueryResult = orderQueryClient.getStatusById(orderId);
        Orders order = objectMapper.convertValue(orderQueryResult.getData(), Orders.class);
        //超时未支付
        if (order.getStatus().equals(OrderStatus.NOT_PAYED)) {
            Result result = orderItemQueryClient.listByOrderId(orderId);
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, OrderItem.class);
            List<OrderItem> orderItems = (List<OrderItem>) objectMapper.convertValue(result.getData(), javaType);
            //修改订单状态
            order.setStatus(OrderStatus.CLOSED);
            order.setCloseType(OrderCloseType.EXPIRED_NOTPAYED);
            //这里分布式事务后期学习后再补上
            Result orderUpdateResult = orderUDClient.update(order);
            List<String> skuIds = orderItems.stream().map(o -> o.getSkuId()).collect(Collectors.toList());
            try {
                boolean isLocked = redissonLock(skuIds, redissonLockMap);
                if (isLocked){
                    //修改库存
                    boolean updateSuccess = updateStock(orderItems);
                    return updateSuccess ? Result.success() : Result.internalServerError();
                }
            } catch (Exception e) {
                log.warn("处理超时未支付订单异常："+e);
                return Result.internalServerError();
            }finally {
                redissonUnlock(redissonLockMap);
            }
        }
        return Result.success();
    }

    public boolean updateStock(List<OrderItem> orderItems) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        List<String> skuIds = orderItems.stream().map(o -> o.getSkuId()).collect(Collectors.toList());
        Result skusResult = productSkuQueryClient.getStockByIds(skuIds);
        JavaType javaType2 = objectMapper.getTypeFactory().constructParametricType(List.class, ProductSku.class);
        List<ProductSku> productSkus = (List<ProductSku>) objectMapper.convertValue(skusResult.getData(), javaType2);
        for (int i = 0; i < orderItems.size(); i++) {
            ProductSku productSku = productSkus.get(i);
            productSku.setStock(productSku.getStock() + orderItems.get(i).getBuyCounts());
            productSkus.set(i,productSku);
        }
//        Result result = productSkuCUDClient.updateBatch(objectMapper.writeValueAsString(productSkus));
        Result result = productSkuCUDClient.updateBatch(productSkus);
        return result.getStatusCode().equals(ResultType.SUCCESS);
    }


    public boolean redissonLock(List<String> listToLock, HashMap<String, RLock> redissonLockMap) throws InterruptedException {
        boolean isLocked = true;
        for (String item : listToLock) {
            RLock lock = redissonClient.getLock(item);
            //添加该套餐的分布式锁（非阻塞锁），3秒重试时间，20s过期时间
            boolean lockSuccess = lock.tryLock(3, 20, TimeUnit.SECONDS);
            //只要有一个商品加锁失败那么整体就是加锁失败（这里只要有一次失败后islocked就会一直为false）
            isLocked = isLocked && lockSuccess;
            if (lockSuccess) {
                redissonLockMap.put(lock.getName(), lock);
            }
        }
        return isLocked;
    }

    public void redissonUnlock(HashMap<String, RLock> redissonLockMap){
        Collection<RLock> redissonLocks = redissonLockMap.values();
        for (RLock redissonLock : redissonLocks) {
            redissonLock.unlock();
        }
    }


}
